package main_package;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map.Entry;

import stemmer.StemmerWrapper;
import synonym.SynonymMatcher;

public class Sentence {

	ArrayList<String> words;
	
	public Sentence(String strSentence)
	{
		// Make more separators besides spaces
		strSentence = RemoveChars(strSentence);
		// Get the words
		String [] sentenceWords = strSentence.split(" ");
		words = new ArrayList<String>();
		for(int i = 0; i < sentenceWords.length; i++)
		{
			// Remove punctuation
			String word = TrimPunctuation(sentenceWords[i]);
			// Stem if needed
			if (Main.isPart2)
				word = StemmerWrapper.Stem(word);
			// To lower case
			if (!word.equals(""))
				words.add(word.toLowerCase());
		}
	}

	public Sentence(List<String> words)
	{
		this.words = new ArrayList<String>();
		this.words.addAll(words);
	}
	private String RemoveChars(String strSentence)
	{
		strSentence = strSentence.replaceAll("-", " ");
		strSentence = strSentence.replaceAll("/", " ");
		return strSentence;
	}
	public String TrimPunctuation(String word)
	{
		return word.trim().replaceAll("[(`?:!.,;'\"]*([a-z]*)[?:!.,;'`)\"-]*", "$1");
	}
	public List<String> GetNGram(int startIndex, int N)
	{
		return words.subList(startIndex, startIndex + N);
	}

	public List<String> SubSentence(int startIndex, int N)
	{
		return words.subList(startIndex, startIndex + N); 
	}
	public int Length()
	{
		return words.size();
	}
	public boolean CompareWordSequences(List<String> sequence1, int startIndex1,
										List<String> sequence2, int startIndex2,
										int length)
	{
		for(int i = 0; i < length; i++)
		{
			// if we are in part 2, compare synonyms
			if(Main.isPart2)
			{
				if(!SynonymMatcher.IsSynonym(sequence1.get(i + startIndex1),(sequence2.get(i + startIndex2))))
			
					return false;
			}
			// we are in part 1
			else
			{
				if(!sequence1.get(i + startIndex1).equals(sequence2.get(i + startIndex2)))
					return false;
			}
		}
			return true;
	}
	
	public Entry<ArrayList<Sentence>,ArrayList<Integer>> ExtractNGrams(int N)
	{
		ArrayList<Sentence> ngrams = new ArrayList<Sentence>();
		ArrayList<Integer> quantities = new ArrayList<Integer>();
		for(int i = 0; i < words.size() - (N - 1); i++)
		{
			Sentence currNGram = new Sentence(words.subList(i, i + N));
			// if not added before, add the n-gram
			if(!ngrams.contains(currNGram))
			{
				ngrams.add(currNGram);
				quantities.add(0);
			}
			
			int ngramIndex = ngrams.indexOf(currNGram);
			
			// Update the number of this n-gram's occurances
			quantities.set(ngramIndex, quantities.get(ngramIndex) + 1);
			
		}
		
		return new AbstractMap.SimpleEntry<ArrayList<Sentence>,ArrayList<Integer>>(ngrams, quantities);
	}
	public boolean equals(Object o)
	{
		Sentence s2 =(Sentence)o;
		if(words.size() != s2.Length())
			return false;

		// Compare each word in the two sentences
		for(int i = 0; i < words.size(); i++)
		{
			if((words.get(i)).compareTo(s2.GetWords().get(i)) != 0)
				return false;
		}
	
		return true;
	}
	
	public ListIterator<String> GetIterator() {
		return words.listIterator();
	}

	public int FindNumOfSequenceOccurances(List<String> sequence)
	{
		int count = 0;
		for(int i = 0; i < words.size() - (sequence.size() - 1); i++)
		{
			// We found a good beginning
			if(words.get(i).compareTo(sequence.get(0)) == 0)
			{
				// Compare the n-gram
				if(CompareWordSequences(this.words, i, sequence, 0, sequence.size()))
					count++;
			}
		}
		
		return count;
	}

	public List<String> GetWords() {

		return words;
	}
}
